/*****************************************************************************************
   
   Copyright (c) Microsoft Corporation. All rights reserved.

   Use of this code sample is subject to the terms of the Microsoft
   Public License, a copy of which should always be distributed with
   this file.  You can also access a copy of this license agreement at:
   http://www.microsoft.com/opensource/licenses.mspx#Ms-PL

 ****************************************************************************************/
using System;

namespace Microsoft.CSA.FeedSync.FeedSyncLibrary
{
    public class History
    {
        private System.Xml.XmlElement m_XmlElement;

        private System.DateTime? m_WhenDateTime;

        private string m_By;
        
        private uint m_Sequence;

        private Microsoft.CSA.FeedSync.FeedSyncLibrary.Sync m_Sync;

        public History(System.Xml.XmlElement i_HistoryXmlElement)
        {
            if (i_HistoryXmlElement == null)
                throw new System.ArgumentException("i_HistoryXmlElement must be non-null!");

            bool InvalidXmlElement =
                (i_HistoryXmlElement.LocalName != Microsoft.CSA.FeedSync.FeedSyncLibrary.Constants.HISTORY_ELEMENT_NAME) ||
                (i_HistoryXmlElement.NamespaceURI != Microsoft.CSA.FeedSync.FeedSyncLibrary.Constants.FEEDSYNC_XML_NAMESPACE_URI);

            if (InvalidXmlElement)
                throw new System.Exception("Invalid i_HistoryXmlElement!");

            m_XmlElement = i_HistoryXmlElement;

            m_Sequence = System.Convert.ToUInt32(i_HistoryXmlElement.GetAttribute(Microsoft.CSA.FeedSync.FeedSyncLibrary.Constants.SEQUENCE_ATTRIBUTE));

            if (i_HistoryXmlElement.HasAttribute(Microsoft.CSA.FeedSync.FeedSyncLibrary.Constants.WHEN_ATTRIBUTE))
            {
                string When = i_HistoryXmlElement.GetAttribute(Microsoft.CSA.FeedSync.FeedSyncLibrary.Constants.WHEN_ATTRIBUTE);
                m_WhenDateTime = System.Convert.ToDateTime(When).ToUniversalTime();
            }
            
            if (i_HistoryXmlElement.HasAttribute(Microsoft.CSA.FeedSync.FeedSyncLibrary.Constants.BY_ATTRIBUTE))
                m_By = i_HistoryXmlElement.GetAttribute(Microsoft.CSA.FeedSync.FeedSyncLibrary.Constants.BY_ATTRIBUTE);

            this.Validate();
        }

        public History(Microsoft.CSA.FeedSync.FeedSyncLibrary.Sync i_Sync, uint i_Sequence, System.DateTime? i_WhenDateTime, string i_By)
        {
            m_Sequence = i_Sequence;
            m_By = i_By;

            if (i_WhenDateTime.HasValue)
                m_WhenDateTime = ((System.DateTime)i_WhenDateTime).ToUniversalTime();

            string HistoryElementName = System.String.Format
                (
                "{0}:{1}",
                i_Sync.NamespacePrefix,
                Microsoft.CSA.FeedSync.FeedSyncLibrary.Constants.HISTORY_ELEMENT_NAME
                );

            m_XmlElement = i_Sync.XmlElement.OwnerDocument.CreateElement(HistoryElementName, Microsoft.CSA.FeedSync.FeedSyncLibrary.Constants.FEEDSYNC_XML_NAMESPACE_URI);
            m_XmlElement.SetAttribute(Microsoft.CSA.FeedSync.FeedSyncLibrary.Constants.SEQUENCE_ATTRIBUTE, m_Sequence.ToString());

            if (!System.String.IsNullOrEmpty(m_By))
                m_XmlElement.SetAttribute(Microsoft.CSA.FeedSync.FeedSyncLibrary.Constants.BY_ATTRIBUTE, m_By);

            if (m_WhenDateTime.HasValue)
                m_XmlElement.SetAttribute(Microsoft.CSA.FeedSync.FeedSyncLibrary.Constants.WHEN_ATTRIBUTE, ((System.DateTime)m_WhenDateTime).ToString(Microsoft.CSA.FeedSync.FeedSyncLibrary.Constants.DATE_STRING_FORMAT));

            this.Validate();
        }

        private void Validate()
        {
            if ((m_WhenDateTime == null) && (System.String.IsNullOrEmpty(m_By)))
                throw new System.ArgumentException("Must have 'when' or 'by' attribute!");

            if (m_Sequence > (System.Math.Pow(2, 32) - 1))
                throw new System.ArgumentException("Invalid value for 'sequence' attribute!");
        }

        public System.DateTime? WhenDateTime
        {
            get
            {
                return m_WhenDateTime;
            }
        }

        public string By
        {
            get
            {
                return m_By;
            }
        }

        public uint Sequence
        {
            get
            {
                return m_Sequence;
            }
            internal set
            {
                if (value <= m_Sequence)
                    throw new System.ArgumentException("Value must be greater than current Sequence!");

                m_XmlElement.SetAttribute(Microsoft.CSA.FeedSync.FeedSyncLibrary.Constants.SEQUENCE_ATTRIBUTE, m_Sequence.ToString());
            }
        }

        public Microsoft.CSA.FeedSync.FeedSyncLibrary.Sync Sync
        {
            get
            {
                return m_Sync;
            }
            internal set
            {
                if (value == null)
                    throw new System.ArgumentException("Value must be non-null!");

                m_Sync = value;
            }
        }

        public System.Xml.XmlElement XmlElement
        {
            get
            {
                return m_XmlElement;
            }
        }

        public bool IsSubsumedBy(Microsoft.CSA.FeedSync.FeedSyncLibrary.History i_History)
        {
            bool Subsumed = false;

            if (!System.String.IsNullOrEmpty(m_By))
            {
                Subsumed =
                    (m_By == i_History.By) &&
                    (i_History.Sequence >= m_Sequence);
            }
            else
            {
                Subsumed =
                    (m_WhenDateTime == i_History.WhenDateTime) &&
                    (m_Sequence == i_History.Sequence);
            }

            return Subsumed;
        }
    }
}
